<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
  <title>A simple libpng example program</title>
  <link rev="made" href="mailto:gc@mandranokespamsoft.com" />
  <meta name="keywords" content="linux libpng program code example simple" />

<link rel="stylesheet" type="text/css" href="/~gc/style.css" media="screen" />
</head>

<body bgcolor="#FFFFFF" text="#000000" link="#0000ee" vlink="#551a8b">

  <h1 align="center">A simple libpng example program</h1>

<hr />

  <h2>Intro</h2>

  <p>
  Sometimes, even if <a href="http://www.gimp.org/">Gimp</a> can
  do wonderful things, one may want to iterate over the pixels of
  a file to compute things on it. One solution is to script gimp
  using scheme or perl. Another one is to use the libpng to read
  and write png files, computing anything necessary in the
  middle. Since I didn't find myself a "simple" example program
  using libpng, I had to more or less hack mine, so I publish it
  there after. It's short and simple - that's the point.
  </p>

  <p>
  Here is the <a href="../resource/libpng-short-example.c">plain
  text version</a> - check next paragraph for the beautified one.
  </p>

<hr />

  <h2>The beautified code</h2>

    <table bgcolor="#2f4f4f" width="100%">
    <td>
<pre style="background-color:#2f4f4f"><font color="#f5deb3"><font color="#bebebe">/*
 * Copyright 2002-2008 Guillaume Cottenceau.
 *
 * This software may be freely redistributed under the terms
 * of the X11 license.
 *
 */</font>

#<font color="#b0c4de">include</font> <font color="#00cd00">&lt;unistd.h&gt;</font>
#<font color="#b0c4de">include</font> <font color="#00cd00">&lt;stdlib.h&gt;</font>
#<font color="#b0c4de">include</font> <font color="#00cd00">&lt;stdio.h&gt;</font>
#<font color="#b0c4de">include</font> <font color="#00cd00">&lt;string.h&gt;</font>
#<font color="#b0c4de">include</font> <font color="#00cd00">&lt;stdarg.h&gt;</font>

#<font color="#b0c4de">define</font> <font color="#9ac0cd">PNG_DEBUG</font> <font color="#cdcd00">3</font>
#<font color="#b0c4de">include</font> <font color="#00cd00">&lt;png.h&gt;</font>

<font color="#98fb98">void</font> <font color="#b2dfee">abort_</font><font color="#00ffff">(</font><font color="#ffa500">const</font> <font color="#98fb98">char</font> * <font color="#9ac0cd">s</font>, ...<font color="#00ffff">)</font>
<font color="#00ffff">{</font>
	va_list args<font color="#00ffff">;</font>
	va_start<font color="#00ffff">(</font>args, s<font color="#00ffff">);</font>
	vfprintf<font color="#00ffff">(</font>stderr, s, args<font color="#00ffff">);</font>
	fprintf<font color="#00ffff">(</font>stderr, <font color="#00cd00">&quot;\n&quot;</font><font color="#00ffff">);</font>
	va_end<font color="#00ffff">(</font>args<font color="#00ffff">);</font>
	abort<font color="#00ffff">();</font>
<font color="#00ffff">}</font>

<font color="#98fb98">int</font> <font color="#9ac0cd">x</font>, <font color="#9ac0cd">y</font><font color="#00ffff">;</font>

<font color="#98fb98">int</font> <font color="#9ac0cd">width</font>, <font color="#9ac0cd">height</font><font color="#00ffff">;</font>
<font color="#98fb98">png_byte</font> <font color="#9ac0cd">color_type</font><font color="#00ffff">;</font>
<font color="#98fb98">png_byte</font> <font color="#9ac0cd">bit_depth</font><font color="#00ffff">;</font>

<font color="#98fb98">png_structp</font> <font color="#9ac0cd">png_ptr</font><font color="#00ffff">;</font>
<font color="#98fb98">png_infop</font> <font color="#9ac0cd">info_ptr</font><font color="#00ffff">;</font>
<font color="#98fb98">int</font> <font color="#9ac0cd">number_of_passes</font><font color="#00ffff">;</font>
<font color="#98fb98">png_bytep</font> * <font color="#9ac0cd">row_pointers</font><font color="#00ffff">;</font>

<font color="#98fb98">void</font> <font color="#b2dfee">read_png_file</font><font color="#00ffff">(</font><font color="#98fb98">char</font>* <font color="#9ac0cd">file_name</font><font color="#00ffff">)</font>
<font color="#00ffff">{</font>
	<font color="#98fb98">char</font> <font color="#9ac0cd">header</font><font color="#00ffff">[</font><font color="#cdcd00">8</font><font color="#00ffff">];</font>	<font color="#bebebe">// 8 is the maximum size that can be checked
</font>
	<font color="#bebebe">/* open file and test for it being a png */</font>
	<font color="#98fb98">FILE</font> *<font color="#9ac0cd">fp</font> = fopen<font color="#00ffff">(</font>file_name, <font color="#00cd00">&quot;rb&quot;</font><font color="#00ffff">);</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>!fp<font color="#00ffff">)</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[read_png_file] File %s could not be opened for reading&quot;</font>, file_name<font color="#00ffff">);</font>
	fread<font color="#00ffff">(</font>header, <font color="#cdcd00">1</font>, <font color="#cdcd00">8</font>, fp<font color="#00ffff">);</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>png_sig_cmp<font color="#00ffff">(</font>header, <font color="#cdcd00">0</font>, <font color="#cdcd00">8</font><font color="#00ffff">))</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[read_png_file] File %s is not recognized as a PNG file&quot;</font>, file_name<font color="#00ffff">);</font>


	<font color="#bebebe">/* initialize stuff */</font>
	png_ptr = png_create_read_struct<font color="#00ffff">(</font>PNG_LIBPNG_VER_STRING, NULL, NULL, NULL<font color="#00ffff">);</font>
	
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>!png_ptr<font color="#00ffff">)</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[read_png_file] png_create_read_struct failed&quot;</font><font color="#00ffff">);</font>

	info_ptr = png_create_info_struct<font color="#00ffff">(</font>png_ptr<font color="#00ffff">);</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>!info_ptr<font color="#00ffff">)</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[read_png_file] png_create_info_struct failed&quot;</font><font color="#00ffff">);</font>

	<font color="#ffa500">if</font> <font color="#00ffff">(</font>setjmp<font color="#00ffff">(</font>png_jmpbuf<font color="#00ffff">(</font>png_ptr<font color="#00ffff">)))</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[read_png_file] Error during init_io&quot;</font><font color="#00ffff">);</font>

	png_init_io<font color="#00ffff">(</font>png_ptr, fp<font color="#00ffff">);</font>
	png_set_sig_bytes<font color="#00ffff">(</font>png_ptr, <font color="#cdcd00">8</font><font color="#00ffff">);</font>

	png_read_info<font color="#00ffff">(</font>png_ptr, info_ptr<font color="#00ffff">);</font>

	width = info_ptr-&gt;width<font color="#00ffff">;</font>
	height = info_ptr-&gt;height<font color="#00ffff">;</font>
	color_type = info_ptr-&gt;color_type<font color="#00ffff">;</font>
	bit_depth = info_ptr-&gt;bit_depth<font color="#00ffff">;</font>

	number_of_passes = png_set_interlace_handling<font color="#00ffff">(</font>png_ptr<font color="#00ffff">);</font>
	png_read_update_info<font color="#00ffff">(</font>png_ptr, info_ptr<font color="#00ffff">);</font>


	<font color="#bebebe">/* read file */</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>setjmp<font color="#00ffff">(</font>png_jmpbuf<font color="#00ffff">(</font>png_ptr<font color="#00ffff">)))</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[read_png_file] Error during read_image&quot;</font><font color="#00ffff">);</font>

	row_pointers = <font color="#00ffff">(</font>png_bytep*<font color="#00ffff">)</font> malloc<font color="#00ffff">(</font><font color="#ffa500">sizeof</font><font color="#00ffff">(</font>png_bytep<font color="#00ffff">)</font> * height<font color="#00ffff">);</font>
	<font color="#ffa500">for</font> <font color="#00ffff">(</font>y=<font color="#cdcd00">0</font><font color="#00ffff">;</font> y&lt;height<font color="#00ffff">;</font> y++<font color="#00ffff">)</font>
		row_pointers<font color="#00ffff">[</font>y<font color="#00ffff">]</font> = <font color="#00ffff">(</font>png_byte*<font color="#00ffff">)</font> malloc<font color="#00ffff">(</font>info_ptr-&gt;rowbytes<font color="#00ffff">);</font>

	png_read_image<font color="#00ffff">(</font>png_ptr, row_pointers<font color="#00ffff">);</font>

        fclose<font color="#00ffff">(</font>fp<font color="#00ffff">);</font>
<font color="#00ffff">}</font>


<font color="#98fb98">void</font> <font color="#b2dfee">write_png_file</font><font color="#00ffff">(</font><font color="#98fb98">char</font>* <font color="#9ac0cd">file_name</font><font color="#00ffff">)</font>
<font color="#00ffff">{</font>
	<font color="#bebebe">/* create file */</font>
	<font color="#98fb98">FILE</font> *<font color="#9ac0cd">fp</font> = fopen<font color="#00ffff">(</font>file_name, <font color="#00cd00">&quot;wb&quot;</font><font color="#00ffff">);</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>!fp<font color="#00ffff">)</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[write_png_file] File %s could not be opened for writing&quot;</font>, file_name<font color="#00ffff">);</font>


	<font color="#bebebe">/* initialize stuff */</font>
	png_ptr = png_create_write_struct<font color="#00ffff">(</font>PNG_LIBPNG_VER_STRING, NULL, NULL, NULL<font color="#00ffff">);</font>
	
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>!png_ptr<font color="#00ffff">)</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[write_png_file] png_create_write_struct failed&quot;</font><font color="#00ffff">);</font>

	info_ptr = png_create_info_struct<font color="#00ffff">(</font>png_ptr<font color="#00ffff">);</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>!info_ptr<font color="#00ffff">)</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[write_png_file] png_create_info_struct failed&quot;</font><font color="#00ffff">);</font>

	<font color="#ffa500">if</font> <font color="#00ffff">(</font>setjmp<font color="#00ffff">(</font>png_jmpbuf<font color="#00ffff">(</font>png_ptr<font color="#00ffff">)))</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[write_png_file] Error during init_io&quot;</font><font color="#00ffff">);</font>

	png_init_io<font color="#00ffff">(</font>png_ptr, fp<font color="#00ffff">);</font>


	<font color="#bebebe">/* write header */</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>setjmp<font color="#00ffff">(</font>png_jmpbuf<font color="#00ffff">(</font>png_ptr<font color="#00ffff">)))</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[write_png_file] Error during writing header&quot;</font><font color="#00ffff">);</font>

	png_set_IHDR<font color="#00ffff">(</font>png_ptr, info_ptr, width, height,
		     bit_depth, color_type, PNG_INTERLACE_NONE,
		     PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE<font color="#00ffff">);</font>

	png_write_info<font color="#00ffff">(</font>png_ptr, info_ptr<font color="#00ffff">);</font>


	<font color="#bebebe">/* write bytes */</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>setjmp<font color="#00ffff">(</font>png_jmpbuf<font color="#00ffff">(</font>png_ptr<font color="#00ffff">)))</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[write_png_file] Error during writing bytes&quot;</font><font color="#00ffff">);</font>

	png_write_image<font color="#00ffff">(</font>png_ptr, row_pointers<font color="#00ffff">);</font>


	<font color="#bebebe">/* end write */</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>setjmp<font color="#00ffff">(</font>png_jmpbuf<font color="#00ffff">(</font>png_ptr<font color="#00ffff">)))</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[write_png_file] Error during end of write&quot;</font><font color="#00ffff">);</font>

	png_write_end<font color="#00ffff">(</font>png_ptr, NULL<font color="#00ffff">);</font>

        <font color="#bebebe">/* cleanup heap allocation */</font>
	<font color="#ffa500">for</font> <font color="#00ffff">(</font>y=<font color="#cdcd00">0</font><font color="#00ffff">;</font> y&lt;height<font color="#00ffff">;</font> y++<font color="#00ffff">)</font>
		free<font color="#00ffff">(</font>row_pointers<font color="#00ffff">[</font>y<font color="#00ffff">]);</font>
	free<font color="#00ffff">(</font>row_pointers<font color="#00ffff">);</font>

        fclose<font color="#00ffff">(</font>fp<font color="#00ffff">);</font>
<font color="#00ffff">}</font>


<font color="#98fb98">void</font> <font color="#b2dfee">process_file</font><font color="#00ffff">(</font><font color="#98fb98">void</font><font color="#00ffff">)</font>
<font color="#00ffff">{</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>info_ptr-&gt;color_type != PNG_COLOR_TYPE_RGBA<font color="#00ffff">)</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;[process_file] color_type of input file must be PNG_COLOR_TYPE_RGBA (is %d)&quot;</font>,
                       info_ptr-&gt;color_type<font color="#00ffff">);</font>

	<font color="#ffa500">for</font> <font color="#00ffff">(</font>y=<font color="#cdcd00">0</font><font color="#00ffff">;</font> y&lt;height<font color="#00ffff">;</font> y++<font color="#00ffff">)</font> <font color="#00ffff">{</font>
		png_byte* row = row_pointers<font color="#00ffff">[</font>y<font color="#00ffff">];</font>
		<font color="#ffa500">for</font> <font color="#00ffff">(</font>x=<font color="#cdcd00">0</font><font color="#00ffff">;</font> x&lt;width<font color="#00ffff">;</font> x++<font color="#00ffff">)</font> <font color="#00ffff">{</font>
			png_byte* ptr = &amp;<font color="#00ffff">(</font>row<font color="#00ffff">[</font>x*<font color="#cdcd00">4</font><font color="#00ffff">]);</font>
			printf<font color="#00ffff">(</font><font color="#00cd00">&quot;Pixel at position [ %d - %d ] has the following RGBA values: %d - %d - %d - %d\n&quot;</font>,
			       x, y, ptr<font color="#00ffff">[</font><font color="#cdcd00">0</font><font color="#00ffff">]</font>, ptr<font color="#00ffff">[</font><font color="#cdcd00">1</font><font color="#00ffff">]</font>, ptr<font color="#00ffff">[</font><font color="#cdcd00">2</font><font color="#00ffff">]</font>, ptr<font color="#00ffff">[</font><font color="#cdcd00">3</font><font color="#00ffff">]);</font>

			<font color="#bebebe">/* set red value to 0 and green value to the blue one */</font>
			ptr<font color="#00ffff">[</font><font color="#cdcd00">0</font><font color="#00ffff">]</font> = <font color="#cdcd00">0</font><font color="#00ffff">;</font>
			ptr<font color="#00ffff">[</font><font color="#cdcd00">1</font><font color="#00ffff">]</font> = ptr<font color="#00ffff">[</font><font color="#cdcd00">2</font><font color="#00ffff">];</font>
		<font color="#00ffff">}</font>
	<font color="#00ffff">}</font>

<font color="#00ffff">}</font>


<font color="#98fb98">int</font> <font color="#b2dfee">main</font><font color="#00ffff">(</font><font color="#98fb98">int</font> <font color="#9ac0cd">argc</font>, <font color="#98fb98">char</font> **<font color="#9ac0cd">argv</font><font color="#00ffff">)</font>
<font color="#00ffff">{</font>
	<font color="#ffa500">if</font> <font color="#00ffff">(</font>argc != <font color="#cdcd00">3</font><font color="#00ffff">)</font>
		abort_<font color="#00ffff">(</font><font color="#00cd00">&quot;Usage: program_name &lt;file_in&gt; &lt;file_out&gt;&quot;</font><font color="#00ffff">);</font>

	read_png_file<font color="#00ffff">(</font>argv<font color="#00ffff">[</font><font color="#cdcd00">1</font><font color="#00ffff">]);</font>
	process_file<font color="#00ffff">();</font>
	write_png_file<font color="#00ffff">(</font>argv<font color="#00ffff">[</font><font color="#cdcd00">2</font><font color="#00ffff">]);</font>

        <font color="#ffa500">return</font> <font color="#cdcd00">0</font><font color="#00ffff">;</font>
<font color="#00ffff">}</font></font></pre>
</td>
</table>

        <p>Thanks to Sbi for some comments and improvements.</p>

<hr />

      <p>
      Last update: Sat Sep 27 21:08:05 2008
      </p>

</body>

</html>
